package com.lineage.server.model;

import com.lineage.config.ConfigOther;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.serverpackets.S_HPMeter;
import com.lineage.server.serverpackets.S_PacketBoxParty;
import com.lineage.server.serverpackets.S_ServerMessage;
import com.lineage.server.serverpackets.ServerBasePacket;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class L1Party {
  private static final Log _log = LogFactory.getLog(L1Party.class);
  
  public static final int MAXPT = ConfigOther.partycount;
  
  private final ConcurrentHashMap<Integer, L1PcInstance> _membersList = new ConcurrentHashMap<>();
  
  private L1PcInstance _leader = null;
  
  private boolean _isLeader = false;
  
  public void addMember(L1PcInstance pc) {
    try {
      int key = 1;
      if (pc == null)
        throw new NullPointerException(); 
      if (this._membersList.size() == MAXPT || this._membersList.contains(pc))
        return; 
      boolean hpUpdate = false;
      if (this._membersList.isEmpty()) {
        setLeader(pc);
      } else {
        hpUpdate = true;
      } 
      while (this._membersList.get(Integer.valueOf(key)) != null)
        key++; 
      this._membersList.put(Integer.valueOf(key), pc);
      pc.setParty(this);
      Iterator<L1PcInstance> iterator = this._membersList.values().iterator();
      while (iterator.hasNext()) {
        L1PcInstance member = iterator.next();
        if (!member.equals(this._leader)) {
          member.sendPackets((ServerBasePacket)new S_PacketBoxParty(member, this));
        } else if (this._isLeader) {
          member.sendPackets((ServerBasePacket)new S_PacketBoxParty(pc));
        } 
        member.sendPackets((ServerBasePacket)new S_PacketBoxParty(this, member));
      } 
      if (!this._isLeader)
        this._isLeader = true; 
      if (hpUpdate)
        createMiniHp(pc); 
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  private void removeMember(L1PcInstance pc) {
    try {
      int removeKey = -1;
      Iterator<Integer> iterator = this._membersList.keySet().iterator();
      while (iterator.hasNext()) {
        int key = ((Integer)iterator.next()).intValue();
        L1PcInstance tgpc = this._membersList.get(Integer.valueOf(key));
        if (pc.equals(tgpc))
          removeKey = key; 
      } 
      if (removeKey != -1) {
        this._membersList.remove(Integer.valueOf(removeKey));
        pc.setParty(null);
        if (!this._membersList.isEmpty())
          deleteMiniHp(pc); 
      } 
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  public int partyUserInMap(short mapid) {
    int i = 0;
    if (this._membersList.isEmpty())
      return 0; 
    if (this._membersList.size() <= 0)
      return 0; 
    Iterator<L1PcInstance> iterator = this._membersList.values().iterator();
    while (iterator.hasNext()) {
      L1PcInstance tgpc = iterator.next();
      short tgpcMapid = tgpc.getMapId();
      if (tgpcMapid == mapid)
        i++; 
    } 
    return i;
  }
  
  public boolean isVacancy() {
    return (this._membersList.size() < MAXPT);
  }
  
  public int getVacancy() {
    return MAXPT - this._membersList.size();
  }
  
  public boolean isMember(L1PcInstance pc) {
    Iterator<L1PcInstance> iterator = this._membersList.values().iterator();
    while (iterator.hasNext()) {
      L1PcInstance tgpc = iterator.next();
      if (pc.equals(tgpc))
        return true; 
    } 
    return false;
  }
  
  public void setLeader(L1PcInstance pc) {
    this._leader = pc;
  }
  
  public L1PcInstance getLeader() {
    return this._leader;
  }
  
  public int getLeaderID() {
    return this._leader.getId();
  }
  
  public boolean isLeader(L1PcInstance pc) {
    return (pc.getId() == this._leader.getId());
  }
  
  public String getMembersNameList() {
    StringBuilder stringBuilder = new StringBuilder();
    if (this._membersList.isEmpty())
      return null; 
    if (this._membersList.size() <= 0)
      return null; 
    Iterator<L1PcInstance> iterator = this._membersList.values().iterator();
    while (iterator.hasNext()) {
      L1PcInstance pc = iterator.next();
      stringBuilder.append(String.valueOf(String.valueOf(pc.getName())) + " ");
    } 
    return stringBuilder.toString();
  }
  
  private void createMiniHp(L1PcInstance pc) {
    if (this._membersList.isEmpty())
      return; 
    if (this._membersList.size() <= 0)
      return; 
    Iterator<L1PcInstance> iterator = this._membersList.values().iterator();
    while (iterator.hasNext()) {
      L1PcInstance member = iterator.next();
      member.sendPackets((ServerBasePacket)new S_HPMeter(pc.getId(), 100 * pc.getCurrentHp() / pc.getMaxHp()));
      pc.sendPackets((ServerBasePacket)new S_HPMeter(member.getId(), 100 * member.getCurrentHp() / member.getMaxHp()));
    } 
  }
  
  private void deleteMiniHp(L1PcInstance pc) {
    if (this._membersList.isEmpty())
      return; 
    if (this._membersList.size() <= 0)
      return; 
    Iterator<Map.Entry<Integer, L1PcInstance>> iterator = this._membersList.entrySet().iterator();
    while (iterator.hasNext()) {
      Map.Entry<Integer, L1PcInstance> info = iterator.next();
      L1PcInstance member = info.getValue();
      pc.sendPackets((ServerBasePacket)new S_HPMeter(member.getId(), 255));
      member.sendPackets((ServerBasePacket)new S_HPMeter(pc.getId(), 255));
    } 
  }
  
  public void updateMiniHP(L1PcInstance pc) {
    if (this._membersList.isEmpty())
      return; 
    if (this._membersList.size() <= 0)
      return; 
    Iterator<L1PcInstance> iterator = this._membersList.values().iterator();
    while (iterator.hasNext()) {
      L1PcInstance member = iterator.next();
      member.sendPackets((ServerBasePacket)new S_HPMeter(pc.getId(), 100 * pc.getCurrentHp() / pc.getMaxHp()));
    } 
  }
  
  public void breakup() {
    if (this._membersList.isEmpty())
      return; 
    if (this._membersList.size() <= 0)
      return; 
    Iterator<Map.Entry<Integer, L1PcInstance>> iterator = this._membersList.entrySet().iterator();
    while (iterator.hasNext()) {
      Map.Entry<Integer, L1PcInstance> info = iterator.next();
      L1PcInstance member = info.getValue();
      removeMember(member);
      member.sendPackets((ServerBasePacket)new S_ServerMessage(418));
    } 
  }
  
  public void leaveMember(L1PcInstance pc) {
    if (isLeader(pc)) {
      breakup();
    } else if (getNumOfMembers() == 2) {
      removeMember(pc);
      L1PcInstance leader = getLeader();
      removeMember(leader);
      sendLeftMessage(pc, pc);
      sendLeftMessage(leader, pc);
      leader.sendPackets((ServerBasePacket)new S_ServerMessage(418));
      pc.sendPackets((ServerBasePacket)new S_ServerMessage(418));
    } else {
      removeMember(pc);
      Iterator<Map.Entry<Integer, L1PcInstance>> iterator = this._membersList.entrySet().iterator();
      while (iterator.hasNext()) {
        Map.Entry<Integer, L1PcInstance> info = iterator.next();
        L1PcInstance member = info.getValue();
        sendLeftMessage(member, pc);
      } 
      sendLeftMessage(pc, pc);
    } 
  }
  
  public void kickMember(L1PcInstance pc) {
    if (getNumOfMembers() == 2) {
      removeMember(pc);
      L1PcInstance leader = getLeader();
      removeMember(leader);
      sendLeftMessage(pc, pc);
      sendLeftMessage(leader, pc);
      leader.sendPackets((ServerBasePacket)new S_ServerMessage(418));
      pc.sendPackets((ServerBasePacket)new S_ServerMessage(418));
    } else {
      removeMember(pc);
      Iterator<L1PcInstance> iterator = this._membersList.values().iterator();
      while (iterator.hasNext()) {
        L1PcInstance member = iterator.next();
        sendLeftMessage(member, pc);
      } 
      sendLeftMessage(pc, pc);
    } 
    pc.sendPackets((ServerBasePacket)new S_ServerMessage(419));
  }
  
  public ConcurrentHashMap<Integer, L1PcInstance> partyUsers() {
    return this._membersList;
  }
  
  public int getNumOfMembers() {
    return this._membersList.size();
  }
  
  private void sendLeftMessage(L1PcInstance sendTo, L1PcInstance left) {
    try {
      sendTo.sendPackets((ServerBasePacket)new S_ServerMessage(420, left.getName()));
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  public final int checkMentor(L1Apprentice apprentice) {
    int checkType = 0;
    Iterator<L1PcInstance> iterator = this._membersList.values().iterator();
    while (iterator.hasNext()) {
      L1PcInstance member = iterator.next();
      if (apprentice.getMaster().getId() == member.getId()) {
        checkType += 4;
        continue;
      } 
      if (!apprentice.getTotalList().contains(member))
        continue; 
      checkType++;
    } 
    return checkType;
  }
  
  public void msgToAll() {
    Iterator<L1PcInstance> iterator = this._membersList.values().iterator();
    while (iterator.hasNext()) {
      L1PcInstance member = iterator.next();
      if (!member.equals(this._leader))
        member.sendPackets((ServerBasePacket)new S_PacketBoxParty(this._leader.getId(), this._leader.getName())); 
    } 
  }
  
  public L1PcInstance partyUser() {
    L1PcInstance user = null;
    Iterator<L1PcInstance> iterator = this._membersList.values().iterator();
    while (iterator.hasNext()) {
      L1PcInstance pc = iterator.next();
      if (user == null && !this._leader.equals(pc))
        user = pc; 
    } 
    return user;
  }
  
  public List<String> getPartyMembers() {
    List<String> partyMembers = new CopyOnWriteArrayList<>();
    Iterator<L1PcInstance> iterator = this._membersList.values().iterator();
    while (iterator.hasNext()) {
      L1PcInstance pc = iterator.next();
      if (!this._leader.equals(pc))
        partyMembers.add(pc.getName()); 
    } 
    return partyMembers;
  }
}
